import random
import re
from datetime import datetime

from flask import request, abort, current_app, make_response, jsonify, session
from info import redis_store, constants, db
from info.libs.yuntongxun import sms
from info.models import User
from info.ulits.captcha.captcha import captcha
from info.ulits.response_code import RET
from . import passport_blu


@passport_blu.route("/register", methods=['POST'])
def register():
    """
    注册的逻辑
    # 1。获取参数
    # 2。校验参数
    # 3。取到服务器保存的真实验证码
    # 4。校验用户输入的验证码
    # 5。如果一致，初始化User模型，并且赋值属性
    # 6。将User模型添加到数据库
    # 7。返回响应

    :return:
    """

    # 1。获取参数
    params_dict = request.json
    mobile = params_dict.get("mobile")
    smscode = params_dict.get("smscode")
    password = params_dict.get("password")

    # 2。校验参数(是否齐全，手机号要再次验证，以防接收验证码后用户更改手机号内容)
    if not all([mobile, smscode, password]):
        return jsonify(errno=RET.PARAMERR, errmsg="请完善信息")
    if not re.match("1[356789]\\d{9}", mobile):
        return jsonify(errno=RET.PARAMERR, errmas="手机号格式不正确")

    # 3。取到服务器保存的真实验证码
    try:
        real_sms_code = redis_store.get("SMS" + mobile)
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.DBERR, errmsg="数据库查询短信验证码错误")
    if not smscode:
        return jsonify(errno=RET.NODATA, errmsg="短信验证码已过期")

    # 4。校验用户输入的验证码
    if real_sms_code != smscode:
        return jsonify(errno=RET.DATAERR, errmsg="短信验证码输入错误")

    # 5。如果一致，初始化User模型，并且赋值属性
    user = User()
    user.mobile = mobile
    user.nick_name = mobile
    # TODO 对密码进行处理

    # 6.1。将User模型添加到数据库
    try:
        db.session.add(user)
        db.session.commit()
    except Exception as e:
        current_app.logger.error(e)
        db.session.rollback()
        return jsonify(errno=RET.DBERR, errmsg="数据库保存用户信息出错")
    # 6.2。达到注册成功就顺便登陆上（往session中存入数据：应该是使用cookie的那个session 吧）
    session["user_name"] = user.id  # 这个id应该是数据表中的主键
    session["mobile"] = user.mobile
    session["nick_name"] = user.nick_name
    session["last_login"] = datetime.now()

    # 7。返回响应
    return jsonify(errno=RET.OK,errmsg="注册成功！")


@passport_blu.route("/sms_code", methods=["POST"])
def send_sms_code():
    """
    发送短信的逻辑
    # 1、获取参数：手机号 图片验证码 图片验证码的随机值key
    # 2、参数校验：是否符合规则/是否有值
    # 3、从redis中取出真实的图片内容的key和value
    # 4、与用户的验证码内容进行对比
    # 5、如果验证通过，生成短信验证码的内容
    # 6、将短信验证码内容保存到redis中，并将验证码的内容发送给第三方，发送短信验证码
    # 7、告知浏览器发送验证码的结果
    :return:
    """
    # return jsonify(errno=RET.OK, errmsg="短信验证码发送成功")

    # 1、获取参数：手机号 图片验证码 图片验证码的随机值key
    # request.data 取到传过来的参数:json字符串
    # '{"mobile": "18600000000", "image_code":"aaaa", "image_code_id":"kdagjklhagibdgiuahgi"}'
    # params_dict = json.loads(request.data)  和下面的代码一个意思
    params_dict = request.json
    print(params_dict)
    mobile = params_dict.get("mobile")
    image_code = params_dict.get("image_code")
    image_code_id = params_dict.get("image_code_id")

    # 2、参数校验：是否符合规则/是否有值
    if not all([mobile, image_code, image_code_id]):
        # return jsonify(errno="4100", errmsg="参数有误")
        return jsonify(errno=RET.PARAMERR, errmsg="请完善信息")
    if not re.match("1[356789]\\d{9}", mobile):
        return jsonify(errno=RET.PARAMERR, errmas="手机号格式不正确")

    # 3、从redis中取出真实的图片内容的key和value
    try:
        real_image_code = redis_store.get("ImageCodeId_" + image_code_id)
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.DBERR, errmsg="数据库查询图片验证码内容失败")
    if not real_image_code:
        return jsonify(errno=RET.NODATA, errmsg="图片验证码已过期")

    # 4、与用户的图片验证码内容进行对比
    # if real_image_code != image_code_id:
    print(real_image_code.upper())
    print(image_code.upper())
    if real_image_code.upper() != image_code.upper():
        return jsonify(errno=RET.DATAERR, errmsg="图片验证码输入错误")

    # 5、验证通过了，生成短信验证码的内容, 并保存到redis中
    sms_code_str = "%06d" % random.randint(0, 999999)

    # 云通讯还没审核通过，这里的手机验证码先自己写一个数字，绕过去
    # sms_code_str = "890890"
    current_app.logger.debug("短信的内容是：%s" % sms_code_str)

    try:
        redis_store.set("SMS" + mobile, sms_code_str, constants.SMS_CODE_REDIS_EXPIRES)
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.DBERR, errmsg="数据库保存短信验证码时出错")

    # 6、将验证码的内容发送给第三方，发送短信验证码
    result = sms.CCP().send_template_sms(mobile, [sms_code_str, constants.SMS_CODE_REDIS_EXPIRES /5],1)
    if result != 0:
        # 代表发送失败
        return jsonify(errno=RET.THIRDERR,errmsg="发送短息失败")

    # 7、告知浏览器发送验证码的结果
    return jsonify(errno=RET.OK, errmsg="短信验证码发送成功")


@passport_blu.route("/image_code")
def get_image_code():
    """
    生成图片验证码并返回
    1 取到参数
    2 保存参数到redis（还没生成图片呢。。。）
    3 生成图片
    4 返回图片
    5

    老师的步骤：
    1 取到参数
    2 判断参数是否有之（为什么会没值呢）
    3 生成图片验证码
    4 保存图片验证码文字到redis
    5 返回验证码图片

    :return:
    """
    # 1 取到参数
    # args:取到url中？后面的参数,,并设置默认值为None
    image_code_id = request.args.get("imageCodeId", None)

    # 2 判断参数是否有之（为什么会没值呢）
    if not image_code_id:
        return abort(403)  # 主动抛出异常

    # 3 生成图片验证码
    name, text, image = captcha.generate_captcha()
    # with open("image.jpg", "wb") as f:
    #     f.write(image)
    # print("图片保存到了")

    # 4 保存图片验证码文字到redis
    try:
        redis_store.set("ImageCodeId_" + image_code_id, text, constants.IMAGE_CODE_REDIS_EXPIRES)
    except Exception as e:
        current_app.logger.error(e)
        abort(500)
    # 5 返回验证码图片
    # make_response: 创建/生成/设置一个响应
    response = make_response(image)
    response.headers["Content-Type"] = "image/jpg"  # 给响应设置一个headers，里面设置他的Content-Type
    return response
